﻿Imports System
Imports System.CodeDom
Imports System.Diagnostics.CodeAnalysis
Imports System.Globalization
Imports System.Text
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.Activities.Rules
    Friend Class CastExpression
        Inherits RuleExpressionInternal
        ' Methods
        Friend Overrides Sub AnalyzeUsage(ByVal expression As CodeExpression, ByVal analysis As RuleAnalysis, ByVal isRead As Boolean, ByVal isWritten As Boolean, ByVal qualifier As RulePathQualifier)
            Dim expression2 As CodeCastExpression = DirectCast(expression, CodeCastExpression)
            RuleExpressionWalker.AnalyzeUsage(analysis, expression2.Expression, True, False, Nothing)
        End Sub

        Friend Overrides Function Clone(ByVal expression As CodeExpression) As CodeExpression
            Dim expression2 As CodeCastExpression = DirectCast(expression, CodeCastExpression)
            Return New CodeCastExpression { _
                .TargetType = TypeReferenceExpression.CloneType(expression2.TargetType), _
                .Expression = RuleExpressionWalker.Clone(expression2.Expression) _
            }
        End Function

        Friend Overrides Sub Decompile(ByVal expression As CodeExpression, ByVal stringBuilder As StringBuilder, ByVal parentExpression As CodeExpression)
            Dim childExpr As CodeCastExpression = DirectCast(expression, CodeCastExpression)
            Dim expression3 As CodeExpression = childExpr.Expression
            If (expression3 Is Nothing) Then
                Dim exception As New RuleEvaluationException(Messages.NullCastExpr)
                exception.Data.Item("ErrorObject") = childExpr
                Throw exception
            End If
            If (childExpr.TargetType Is Nothing) Then
                Dim exception2 As New RuleEvaluationException(Messages.NullCastType)
                exception2.Data.Item("ErrorObject") = childExpr
                Throw exception2
            End If
            Dim flag As Boolean = RuleDecompiler.MustParenthesize(childExpr, parentExpression)
            If flag Then
                stringBuilder.Append("(")
            End If
            stringBuilder.Append("(")
            RuleDecompiler.DecompileType(stringBuilder, childExpr.TargetType)
            stringBuilder.Append(")")
            RuleExpressionWalker.Decompile(stringBuilder, expression3, childExpr)
            If flag Then
                stringBuilder.Append(")")
            End If
        End Sub

        Friend Overrides Function Evaluate(ByVal expression As CodeExpression, ByVal execution As RuleExecution) As RuleExpressionResult
            Dim expression2 As CodeCastExpression = DirectCast(expression, CodeCastExpression)
            Dim operandValue As Object = RuleExpressionWalker.Evaluate(execution, expression2.Expression).Value
            Dim info As RuleExpressionInfo = execution.Validation.ExpressionInfo(expression2)
            If (info Is Nothing) Then
                Dim exception As New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Messages.ExpressionNotValidated, New Object(0  - 1) {}))
                exception.Data.Item("ErrorObject") = expression2
                Throw exception
            End If
            Dim expressionType As Type = info.ExpressionType
            If (operandValue Is Nothing) Then
                If ConditionHelper.IsNonNullableValueType(expressionType) Then
                    Dim exception2 As New RuleEvaluationException(String.Format(CultureInfo.CurrentCulture, Messages.CastIncompatibleTypes, New Object() { Messages.NullValue, RuleDecompiler.DecompileType(expressionType) }))
                    exception2.Data.Item("ErrorObject") = expression2
                    Throw exception2
                End If
            Else
                operandValue = Executor.AdjustTypeWithCast(execution.Validation.ExpressionInfo(expression2.Expression).ExpressionType, operandValue, expressionType)
            End If
            Return New RuleLiteralResult(operandValue)
        End Function

        Private Shared Function IsNumeric(ByVal type As Type) As Boolean
            Select Case Type.GetTypeCode(type)
                Case TypeCode.Char, TypeCode.[SByte], TypeCode.Byte, TypeCode.Int16, TypeCode.UInt16, TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64, TypeCode.Single, TypeCode.Double, TypeCode.Decimal
                    Return True
            End Select
            Return False
        End Function

        Friend Overrides Function Match(ByVal expression As CodeExpression, ByVal comperand As CodeExpression) As Boolean
            Dim expression2 As CodeCastExpression = DirectCast(expression, CodeCastExpression)
            Dim expression3 As CodeCastExpression = DirectCast(comperand, CodeCastExpression)
            Return (TypeReferenceExpression.MatchType(expression2.TargetType, expression3.TargetType) AndAlso RuleExpressionWalker.Match(expression2.Expression, expression3.Expression))
        End Function

        <SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")> _
        Friend Overrides Function Validate(ByVal expression As CodeExpression, ByVal validation As RuleValidation, ByVal isWritten As Boolean) As RuleExpressionInfo
            Dim expression2 As CodeCastExpression = DirectCast(expression, CodeCastExpression)
            If isWritten Then
                Dim item As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.CannotWriteToExpression, New Object() { GetType(CodeCastExpression).ToString }), &H17A)
                item.UserData.Item("ErrorObject") = expression2
                validation.Errors.Add(item)
                Return Nothing
            End If
            If (expression2.Expression Is Nothing) Then
                Dim error2 As New ValidationError(Messages.NullCastExpr, &H53D)
                error2.UserData.Item("ErrorObject") = expression2
                validation.Errors.Add(error2)
                Return Nothing
            End If
            If TypeOf expression2.Expression Is CodeTypeReferenceExpression Then
                Dim error As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.CodeExpressionNotHandled, New Object() { expression2.Expression.GetType.FullName }), &H548)
                [error].UserData.Item("ErrorObject") = expression2.Expression
                validation.AddError([error])
                Return Nothing
            End If
            If (expression2.TargetType Is Nothing) Then
                Dim error4 As New ValidationError(Messages.NullCastType, &H53D)
                error4.UserData.Item("ErrorObject") = expression2
                validation.Errors.Add(error4)
                Return Nothing
            End If
            Dim info As RuleExpressionInfo = RuleExpressionWalker.Validate(validation, expression2.Expression, False)
            If (info Is Nothing) Then
                Return Nothing
            End If
            Dim expressionType As Type = info.ExpressionType
            Dim type As Type = validation.ResolveType(expression2.TargetType)
            If (type Is Nothing) Then
                Return Nothing
            End If
            If (expressionType Is GetType(NullLiteral)) Then
                If ConditionHelper.IsNonNullableValueType(type) Then
                    Dim error5 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.CastOfNullInvalid, New Object() { RuleDecompiler.DecompileType(type) }), &H53D)
                    error5.UserData.Item("ErrorObject") = expression2
                    validation.Errors.Add(error5)
                    Return Nothing
                End If
            Else
                Dim type3 As Type = expressionType
                If ConditionHelper.IsNullableValueType(type3) Then
                    type3 = type3.GetGenericArguments(0)
                End If
                Dim type4 As Type = type
                If ConditionHelper.IsNullableValueType(type4) Then
                    type4 = type4.GetGenericArguments(0)
                End If
                Dim flag As Boolean = False
                If (type3.IsValueType AndAlso type4.IsValueType) Then
                    If type3.IsEnum Then
                        flag = (type4.IsEnum OrElse CastExpression.IsNumeric(type4))
                    ElseIf type4.IsEnum Then
                        flag = CastExpression.IsNumeric(type3)
                    ElseIf (type3 Is GetType(Char)) Then
                        flag = CastExpression.IsNumeric(type4)
                    ElseIf (type4 Is GetType(Char)) Then
                        flag = CastExpression.IsNumeric(type3)
                    ElseIf (type3.IsPrimitive AndAlso type4.IsPrimitive) Then
                        Try 
                            Convert.ChangeType(Activator.CreateInstance(type3), type4, CultureInfo.CurrentCulture)
                            flag = True
                        Catch exception1 As Exception
                            flag = False
                        End Try
                    End If
                End If
                If Not flag Then
                    Dim error6 As ValidationError
                    flag = RuleValidation.ExplicitConversionSpecified(expressionType, type, error6)
                    If (Not error6 Is Nothing) Then
                        error6.UserData.Item("ErrorObject") = expression2
                        validation.Errors.Add(error6)
                        Return Nothing
                    End If
                End If
                If Not flag Then
                    Dim error7 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.CastIncompatibleTypes, New Object() { RuleDecompiler.DecompileType(expressionType), RuleDecompiler.DecompileType(type) }), &H53D)
                    error7.UserData.Item("ErrorObject") = expression2
                    validation.Errors.Add(error7)
                    Return Nothing
                End If
            End If
            Return New RuleExpressionInfo(type)
        End Function

    End Class
End Namespace

